/**
 * 支付宝
 * 请勿修改此处代码，因为插件更新后此处代码会被覆盖。
 * 作者：VK
 */
const fs = require("fs");
const crypto = require("crypto");
const util = require("./util");
const libs = require('../../libs');

class Alipay {

	constructor(config) {
		let {
			appId, // 商家应用id
			privateKey, // 商家应用私钥
			// 证书（路径形式）
			alipayPublicCertPath, // 支付宝公钥证书路径
			alipayRootCertPath, // 支付宝根证书路径
			appCertPath, // 商家应用公钥证书路径
			// 证书（内容形式）路径和内容二选一即可
			alipayPublicCertContent, // 支付宝公钥证书内容
			alipayRootCertContent, // 支付宝根证书内容
			appCertContent, // 商家应用公钥证书内容
			// 序列号形式
			appCertSn, // 商家应用证书的序列号
			alipayRootCertSn, // 支付宝根证书的序列号
			apiUrl = "https://openapi.alipay.com/gateway.do",
			appAuthToken, // 子商户token
			sandbox // 是否是沙箱模式
		} = config;

		if (sandbox) {
			apiUrl = 'https://openapi.alipaydev.com/gateway.do'
		}

		if (!alipayPublicCertContent && alipayPublicCertPath) {
			alipayPublicCertContent = fs.readFileSync(alipayPublicCertPath);
		}
		if (!alipayRootCertContent && alipayRootCertPath) {
			alipayRootCertContent = fs.readFileSync(alipayRootCertPath);
		}
		if (!appCertContent && appCertPath) {
			appCertContent = fs.readFileSync(appCertPath);
		}
		if (!appCertSn && appCertContent) {
			appCertSn = libs.certutil.alipay.getSN(appCertContent, false);
		}
		if (!alipayRootCertSn && alipayRootCertContent) {
			alipayRootCertSn = libs.certutil.alipay.getSN(alipayRootCertContent, true);
		}

		this.config = {
			appId,
			privateKey,
			alipayPublicCertContent,
			alipayRootCertContent,
			appCertContent,
			appCertSn,
			alipayRootCertSn,
			apiUrl,
			appAuthToken,
			sandbox
		};
	}
	/**
	 * 发起请求
	 */
	async request(obj = {}) {
		let {
			method,
			data = {},
			successText
		} = obj;
		let config = this.config; // 支付配置
		let time = Date.now(); // 当前时间
		// 请求参数
		let params = {
			timestamp: libs.common.timeFormat(time, "yyyy-MM-dd hh:mm:ss"),
			...data,
		};
		if (!params.app_auth_token && config.appAuthToken) {
			params.app_auth_token = config.appAuthToken;
		}
		// 计算签名
		const signData = util.sign(method, params, config);
		// 格式化url和请求参数
		const { url, execParams } = util.formatUrl(signData, config.apiUrl);
		// 发起http请求
		let requestRes = await libs.common.request({
			url: url,
			method: "POST",
			data: execParams
		});
		let res = { code: 0, msg: "" };
		// 解析返回结果
		let result = await util.getRequestRes(requestRes, method);
		if (!result.code || result.code === "10000") {
			// 成功
			res.code = 0;
			res.msg = successText;
		} else {
			// 失败
			res.code = result.sub_code || result.code;
			res.msg = result.sub_msg || result.msg;
		}
		res.result = result; // 将支付宝返回的结果原样返回
		return res;
	}

	/**
	 * 获取请求参数
	 * 内部方法，暂未使用
	 */
	async getOrderStr(obj = {}) {
		let {
			method,
			data = {},
			successText
		} = obj;
		let config = this.config; // 支付配置
		let time = Date.now(); // 当前时间
		// 请求参数
		let params = {
			timestamp: libs.common.timeFormat(time, "yyyy-MM-dd hh:mm:ss"),
			...data,
		};
		// 计算签名
		let signData = util.sign(method, params, config);
		signData = util.sortObj(signData);
		let body = "";
		for (const key in signData) {
			const val = encodeURIComponent(signData[key]);
			body = `${body}${body == "" ? '' : '&'}${key}=${val}`;
		}
		return {
			code: 0,
			body
		};
	}

	/**
	 * 单笔转账到支付宝
	 * 文档：https://opendocs.alipay.com/open/02byuo?ref=api&scene=ca56bca529e64125a2786703c6192d41
	 */
	async transfer(data = {}) {
		let res = await this.request({
			method: "alipay.fund.trans.uni.transfer",
			data: data,
			successText: "请求成功"
		});
		return res;
	}
	/**
	 * code获取openid
	 */
	async code2SessionAlipay(data = {}) {
		let { code } = data;
		let res = await this.request({
			method: "alipay.system.oauth.token",
			data: {
				code,
				grant_type: "authorization_code"
			},
		});
		return res;
	}

	/**
	 * 支付宝资金账户资产查询接口
	 * 文档：https://opendocs.alipay.com/open/1b8a680c_alipay.fund.account.query
	 */
	async queryAccountBalance(data = {}) {
		let res = await this.request({
			method: "alipay.fund.account.query",
			data: data,
			successText: "请求成功"
		});
		return res;
	}

}

module.exports = Alipay;
